﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
namespace SensorDrone.Net.Extensions
{
    /// <summary>
    /// Implements a task to sample sensors and convert them to an observable
    /// </summary>
    class SensorDroneStream :IObservable<Reading>
    {
        private readonly Subject<Reading> _subject = new Subject<Reading>();
        private readonly Task _task;

        public IDisposable Subscribe(IObserver<Reading> observer)
        {
            return _subject.Subscribe(observer);
        }

        public SensorDroneStream(ISensorDrone drone, IEnumerable<string> sensors)
        {
            var tcs = new CancellationTokenSource();
            _task = Task.Run(()=>ObservableTask(drone, sensors, _subject),tcs.Token);
        }

        async private void ObservableTask(ISensorDrone drone, IEnumerable<string> sensors, Subject<Reading> subject)
        {
            try
            {
                var sampling = sensors.ToList();
                while (!drone.Cancelled)
                {
                    foreach (var sensor in sampling)
                    {
                        var reading = await drone.SampleAsync(sensor);
                        if(reading != null)
                            subject.OnNext(reading);
                        else
                        {
                            subject.OnError(new ArgumentNullException("reading",sensor));
                        }
                    }
                    
                }
                subject.OnCompleted();
            }
            catch (Exception error)
            {
                subject.OnError(error);
            }
        }
    }
}
